package utils

import (
	"bufio"
	"fmt"
	"os"
	"sync"
	"sync/atomic"
)

/*
**
* 缓存写入规则:
 1. 大于缓存数量会自动写入
 2. 没写入过会进行一次写入
*/
type loggerTypeFileRec struct {
	poolState int32

	owner *LoggerTypeFileWriter

	lastfilename   string
	typestr        string
	file           *os.File
	fileWriter     *bufio.Writer
	curr_file_size int64
}

var (
	__loggerTypeFileRecPool sync.Pool
)

func initializePool_loggerTypeFileRec() {
	if __loggerTypeFileRecPool.New == nil {
		__loggerTypeFileRecPool.New = func() interface{} {
			rval := &loggerTypeFileRec{}
			return rval
		}
	}
}

func getFileRecFromPool() *loggerTypeFileRec {
	rval := __loggerTypeFileRecPool.Get().(*loggerTypeFileRec)
	rval.typestr = ""
	rval.file = nil
	rval.curr_file_size = 0
	rval.poolState = 1
	return rval
}

func (this *loggerTypeFileRec) Release2Pool() {
	if atomic.CompareAndSwapInt32(&this.poolState, 1, 0) {
		__loggerTypeFileRecPool.Put(this)
	}
}

func (this *loggerTypeFileRec) checkFile(rec *LogRecord) error {
	f1 := string(FormatLogRecord(this.owner.filenamefmt, rec))
	if this.lastfilename == f1 {
		return nil
	}

	if this.file != nil {
		this.file.Close()
		this.file = nil
	}

	currFile := f1 + CombineIfNotEmpty("-", rec.Typestr) + this.owner.fileext

	// 检测新文件是否存在,如果存在则进行更名
	err := CheckRotateFile(currFile)
	if err != nil {
		return err
	}
	err = ForceCreateFilePath(currFile)
	if err != nil {
		return err
	}

	//四位数代表意思
	//特殊权限位，拥有者位，同组用户位，其余用户位
	//读是4，写是2，执行是1
	//7=4+2+1
	//6=4+2
	// 0666表示，特殊权限没有，拥有者可以读写，同组用户可以读写，其余用户可以读写
	fd, err := os.OpenFile(currFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664)
	if err != nil {
		return err
	}

	this.lastfilename = f1
	this.file = fd
	if this.owner.cache_size > 0 {
		this.fileWriter = bufio.NewWriterSize(this.file, int(this.owner.cache_size))

	} else {
		this.fileWriter = bufio.NewWriter(this.file)
	}

	return nil
}

func (this *loggerTypeFileRec) onTaskLogRec(sender *MultiGroupTaskRec) {
	rec := sender.Args[0].(*LogRecord)
	err := this.checkFile(rec)
	if err != nil {
		fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", this.owner.filenamefmt, err)
		return
	}

	msg := string(FormatLogRecord(this.owner.format, rec))
	n, err := fmt.Fprint(this.fileWriter, msg)
	if err != nil {
		fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", this.owner.filenamefmt, err)
		return
	}
	this.curr_file_size += int64(n)
	if this.owner.cache_size <= 0 {
		err := this.fileWriter.Flush()
		if err != nil {
			fmt.Fprintf(os.Stderr, "FileLogWriter(%s) flush err %s\n", this.owner.filenamefmt, err)
		}
	}

	if this.owner.max_file_size > 0 && this.curr_file_size >= this.owner.max_file_size {
		this.Close()
		this.curr_file_size = 0
		this.lastfilename = "" // 下次新建文件
	}
}

func (this *loggerTypeFileRec) Close() {
	if this.file != nil {
		this.fileWriter.Flush()
		this.file.Close()
		this.file = nil
	}

}
